import 'dart:math';

import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher_string.dart';

import '7_slide_transition.dart';

class Demo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("切换时为了尽显丝毫，需要有切换动画"),
          Text("1. Flutter SDK组件已经提供了PageView、TabView等"),
          SizedBox(height: 10),
          Text("2. 通过AnimatedSwitcher组件自定义切换动画"),
          AnimatedSwitcherCounterRoute(),
          SizedBox(height: 10),
          Text("3. AnimatedSwitcher实现原理："),
          Text(
              "didUpdateWidget回调中判断其新旧child 是否发生变化: 如果发生变化，则对旧 child 执行反向退场（reverse）动画，对新child执行正向（forward）入场动画即可。"),
          Text(
              "PS: Flutter还提供了一个AnimatedCrossFade组件，它也可以切换两个子元素，切换过程执行渐隐渐显的动画"),
          SizedBox(height: 30),
          Text("4. AnimatedSwitcher高级用法："),
          Text("4.1 实现一个类似路由平移切换的动画: 旧页面从中间往左退出，新页面从右往中间移入"),
          Text("实现失败... 😄"),
          SliderDemo(),
          SizedBox(height: 10),
          Text("重写SlideTransition，让其反向动画的Offest不要默认，按照我们的需求来反转下：从中间往左退出"),
          SliderDemo2(),
          SizedBox(height: 10),
          Text("4.2 任意方向移动过"),
          Text("从右往左"),
          SliderDemo3(),
          Text("从左往右"),
          SliderDemo3(direction: AxisDirection.right),
          Text("从上往下"),
          SliderDemo3(direction: AxisDirection.down),
          Text("从下往上"),
          SliderDemo3(direction: AxisDirection.up),
          SizedBox(height: 30),
          Text("5. 总结："),
          Text(
              "1. AnimatedSwitcher用来动画对称性，渐隐渐出, 本质是对同一个对象的旧widget执行reverse, 新widegt执行forward"),
          Text("2. 高级用法自己定义transitionBuilder, 让其reverse不原路返回，就能形成平移动画"),
          TextButton(
              onPressed: () {
                launchUrlString(
                    "https://book.flutterchina.club/chapter9/animated_switcher.html");
              },
              child: Text("参考《flutter实战》动画切换组件")),
        ],
      ),
    );
  }
}

class AnimatedSwitcherCounterRoute extends StatefulWidget {
  const AnimatedSwitcherCounterRoute();

  @override
  State createState() => _AnimatedSwitcherCounterRouteState();
}

class _AnimatedSwitcherCounterRouteState
    extends State<AnimatedSwitcherCounterRoute> {
  int _count = 0;

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          AnimatedSwitcher(
            // 新child显示时常
            duration: const Duration(milliseconds: 500),
            // 旧child隐藏时常
            // reverseDuration: const Duration(milliseconds: 2000),
            transitionBuilder: (Widget child, Animation<double> animation) {
              //执行缩放动画
              return ScaleTransition(scale: animation, child: child);
            },
            child: Text(
              '$_count',
              //显示指定key，不同的key会被认为是不同的Text，这样才能执行动画
              key: ValueKey<int>(_count),
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ),
          ElevatedButton(
            child: const Text('+1'),
            onPressed: () {
              setState(() {
                _count += 1;
              });
            },
          ),
        ],
      ),
    );
  }
}

class SliderDemo extends StatefulWidget {
  const SliderDemo({super.key});

  @override
  State<SliderDemo> createState() => _SliderDemoState();
}

class _SliderDemoState extends State<SliderDemo> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        AnimatedSwitcher(
          duration: Duration(milliseconds: 2000),
          transitionBuilder: (Widget child, Animation<double> animation) {
            // (1, 0)的位置是两幅图拼接而成？
            var tween = Tween<Offset>(begin: Offset(1, 0), end: Offset(0, 0));
            return SlideTransition(
              position: tween.animate(animation),
              child: child,
            );
          },
          child: Image.asset(
            "images/hanli.jpeg",
            //显示指定key，不同的key会被认为是不同的Text，这样才能执行动画
            key: ValueKey(Random().nextInt(100)),
            width: 200,
          ),
        ),
        ElevatedButton(
          onPressed: () {
            setState(() {});
          },
          child: Text("start"),
        ),
        Row(),
      ],
    );
  }
}

class SliderDemo2 extends StatefulWidget {
  const SliderDemo2({super.key});

  @override
  State<SliderDemo2> createState() => _SliderDemoState2();
}

class _SliderDemoState2 extends State<SliderDemo2> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        AnimatedSwitcher(
          duration: Duration(milliseconds: 2000),
          transitionBuilder: (Widget child, Animation<double> animation) {
            var tween = Tween<Offset>(begin: Offset(1, 0), end: Offset(0, 0));
            return MySlideTransition(
                position: tween.animate(animation), child: child);
          },
          child: Image.asset(
            "images/hanli.jpeg",
            //显示指定key，不同的key会被认为是不同的Text，这样才能执行动画
            key: ValueKey(Random().nextInt(100)),
            width: 200,
          ),
        ),
        ElevatedButton(
          onPressed: () {
            setState(() {});
          },
          child: Text("start"),
        ),
        Row(),
      ],
    );
  }
}

class SliderDemo3 extends StatefulWidget {
  SliderDemo3({this.direction = AxisDirection.left});
  final AxisDirection? direction;

  @override
  State<SliderDemo3> createState() => _SliderDemoState3();
}

class _SliderDemoState3 extends State<SliderDemo3> {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        AnimatedSwitcher(
          duration: Duration(milliseconds: 2000),
          transitionBuilder: (Widget child, Animation<double> animation) {
            return SlideTransitionX(
              animation: animation,
              direction: widget.direction,
              child: child,
            );
          },
          child: Image.asset(
            "images/hanli.jpeg",
            //显示指定key，不同的key会被认为是不同的Text，这样才能执行动画
            key: ValueKey(Random().nextInt(100)),
            width: 200,
          ),
        ),
        ElevatedButton(
          onPressed: () => setState(() {}),
          child: Text("${widget.direction}"),
        ),
        Row(),
      ],
    );
  }
}

class MySlideTransition extends AnimatedWidget {
  /// The [position] argument must not be null.
  const MySlideTransition({
    super.key,
    required Animation<Offset> position,
    this.transformHitTests = true,
    this.textDirection,
    this.child,
  }) : super(listenable: position);

  /// The animation that controls the position of the child.
  ///
  /// If the current value of the position animation is `(dx, dy)`, the child
  /// will be translated horizontally by `width * dx` and vertically by
  /// `height * dy`, after applying the [textDirection] if available.
  Animation<Offset> get position => listenable as Animation<Offset>;

  /// The direction to use for the x offset described by the [position].
  ///
  /// If [textDirection] is null, the x offset is applied in the coordinate
  /// system of the canvas (so positive x offsets move the child towards the
  /// right).
  ///
  /// If [textDirection] is [TextDirection.rtl], the x offset is applied in the
  /// reading direction such that x offsets move the child towards the left.
  ///
  /// If [textDirection] is [TextDirection.ltr], the x offset is applied in the
  /// reading direction such that x offsets move the child towards the right.
  final TextDirection? textDirection;

  /// Whether hit testing should be affected by the slide animation.
  ///
  /// If false, hit testing will proceed as if the child was not translated at
  /// all. Setting this value to false is useful for fast animations where you
  /// expect the user to commonly interact with the child widget in its final
  /// location and you want the user to benefit from "muscle memory".
  final bool transformHitTests;

  /// The widget below this widget in the tree.
  ///
  /// {@macro flutter.widgets.ProxyWidget.child}
  final Widget? child;

  @override
  Widget build(BuildContext context) {
    Offset offset = position.value;
    // print("textDirection $textDirection"); // textDirection null
    // 这一句应该只有在阿拉伯文才会用到吧？
    if (textDirection == TextDirection.rtl) {
      offset = Offset(-offset.dx, offset.dy);
    }

    // print("offset: $offset; position: ${position.status}");
    if (position.status == AnimationStatus.reverse) {
      // (begin: Offset(-1, 0), end: Offset(0, 0)),

      //然后默认会被外层的AnimatedSwitcher reverse =>
      // (begin: Offset(0, 0), end: Offset(-1, 0))
      offset = Offset(-offset.dx, offset.dy);
    }

    return FractionalTranslation(
      translation: offset,
      transformHitTests: transformHitTests,
      child: child,
    );
  }
}

void main(List<String> args) {
  runApp(MaterialApp(
    home: Scaffold(body: Demo()),
  ));
}
